home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / keyboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  13.0 KB  |  518 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include <termios.h>
  10. #include <errno.h>
  11. #include <ctype.h>
  12. #include <limits.h>
  13. #include <signal.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #ifdef MGR
  18. #  define M_NOFLUSH
  19. #  include "mgr/mgr.h"
  20. #endif
  21.  
  22. #define KEYBOARD_C
  23. #define I_BUFFLOOP_C
  24. #define I_DISPLAY_C
  25. #define I_GETMSG_C
  26. #define I_GETTK_C
  27. #define I_FOLDING_C
  28. #define I_KEYTAB_C
  29. #define I_LOOP_C
  30. #define I_MAIN_C
  31. #define I_MESSAGES_C
  32. #define I_PROMPT_C
  33. #define I_SCREEN_C
  34. #define I_SIGNALS_C
  35. #define I_VIRTUAL_C
  36.  
  37. #include "origami.h"
  38. #include <h/envvar_str.h>
  39. /*}}}  */
  40.  
  41. /*{{{  define _POSIX_VDISABLE to 0377, if bd os doesn't support*/
  42. #ifndef _POSIX_VDISABLE
  43. #  define _POSIX_VDISABLE 0377
  44. #endif
  45. /*}}}  */
  46. /*{{{  variables*/
  47. private struct termios orig, work;
  48. private boolean kbd_is_terminal;
  49. public FILE *kbd_file;
  50. public boolean eight_bits=True;
  51. public boolean echo_active;
  52. public boolean echo_disabled=False;
  53.  
  54. #ifdef MOUSY
  55.   public mouse_typ use_mouse=no_mouse;
  56.   /*{{{  mousecount*/
  57.   public int const mouse_b_count[mouse_supports]=
  58.    { 0
  59. #     ifdef XTERM
  60.         ,XTERM_MOUSE_COUNT
  61. #     endif
  62. #     ifdef MGR
  63.         ,MGR_MOUSE_COUNT
  64. #     endif
  65. #     ifdef OS_MOUSE_TAG
  66.         ,OS_MOUSE_COUNT
  67. #     endif
  68.    };
  69.   /*}}}  */
  70.   /*{{{  mousenames*/
  71.   /*{{{  define the used namelists, or define them to nil*/
  72. #  ifdef XTERM
  73.      private char const * const x_m_n[]=XTERM_MOUSE_NAMES;
  74. #     define X_M_N ,x_m_n
  75. #  else
  76. #     define X_M_N
  77. #  endif
  78. #  ifdef MGR
  79.      private char const * const m_m_n[]=MGR_MOUSE_NAMES;
  80. #     define M_M_N ,m_m_n
  81. #  else
  82. #     define M_M_N
  83. #  endif
  84. #  ifdef OS_MOUSE_NAMES
  85.      private char const * const os_m_n[]=OS_MOUSE_NAMES;
  86. #     define OS_M_N ,os_m_n
  87. #  else
  88. #     define OS_M_N
  89. #  endif
  90.   /*}}}  */
  91.   public char const * const * const mouse_b_names[mouse_supports]=
  92.    { 0
  93.      X_M_N   /* x-names                 */
  94.      M_M_N   /* mgr-names               */
  95.      OS_M_N  /* os-specific mouse names */
  96.    };
  97.   /*}}}  */
  98. # ifdef WINDOW_TITLE_CHANGE
  99.      public int wt_buff_id= -1;
  100.      public char *w_title=0;
  101.      private boolean chg_title=False;
  102. # endif
  103. #endif
  104. /*}}}  */
  105.  
  106. /*{{{  enable_echo*/
  107. public void enable_echo(boolean const echo_on)
  108. {
  109.   echo_active=(!echo_disabled && echo_on);
  110. }
  111. /*}}}  */
  112. /*{{{  switch_echo*/
  113. public void switch_echo(boolean const on)
  114. {
  115.   echo_disabled=!(echo_active=on);
  116. }
  117. /*}}}  */
  118.  
  119. /*{{{  enable_abort*/
  120. public void enable_abort(void)
  121. {
  122.   if (general_abort_key==255) return;
  123.   signal(SIGINT, ori_abort);
  124.   work.c_cc[VINTR]=(char)general_abort_key;
  125.   tcsetattr(fileno(kbd_file), TCSANOW, &work);
  126. }
  127. /*}}}  */
  128. /*{{{  disable_abort*/
  129. public void disable_abort(void)
  130. {
  131.   signal(SIGINT, SIG_IGN);
  132.   work.c_cc[VINTR]=_POSIX_VDISABLE;
  133.   if (tcsetattr(fileno(kbd_file), TCSANOW, &work)<0 && kbd_is_terminal)
  134.   { unsigned char *t;
  135.  
  136.  
  137.     t=get_msg(F_TCS_F,strerror(errno));
  138.     if (running)
  139.        exit_origami(r_init_err,t);
  140.     else
  141.      { oputs(t);
  142.        exit(r_init_err);
  143.      }
  144.   }
  145. }
  146. /*}}}  */
  147.  
  148. /*{{{  init_keyboard*/
  149. public void init_keyboard(void)
  150. {
  151.   /*{{{  set kbd to my terminal*/
  152.   if (!(kbd_is_terminal=isatty(fileno(stdin))) && !no_pipe)
  153.    /*{{{  set startup pipe to stdin and open terminal*/
  154.    { start_pipe=stdin;
  155.      kbd_is_terminal=True;
  156.      kbd_file=fopen(ctermid((char*)0),(char*)"r");
  157.      if (!kbd_file)
  158.       { oputs(get_msg(M_FAILED_TERMINAL));
  159.         exit(r_init_err);
  160.       }
  161.    }
  162.    /*}}}  */
  163.   else
  164.      kbd_file=stdin;
  165.   /*}}}  */
  166.   /*{{{  maybe switch mousehandling on*/
  167. #  ifdef MOUSY
  168.      if (terminal)
  169.       {
  170. #     ifdef XTERM
  171.            if (!strncmp(terminal,XTERM_MOUSE_NAME,sizeof(XTERM_MOUSE_NAME)-1))
  172.             /*{{{  switch xterm to send mouse*/
  173.             {
  174.               send_s_terminal((unsigned char*)XTERM_START_BP);
  175.               use_mouse=xterm;
  176.               if (w_title)
  177.                { chg_title=True;
  178.                  if (!*w_title) w_title=XTERM_DEFAULT_TITLE;
  179.                }
  180.             }
  181.             /*}}}  */
  182. #     endif
  183. #     ifdef MGR
  184.            if (!strncmp(terminal,MGR_MOUSE_NAME,sizeof(MGR_MOUSE_NAME)-1))
  185.             /*{{{  activate catching mgr-events*/
  186.             { char x[33];
  187.  
  188.               fflush(stdout);
  189.               use_mouse=mgr;
  190.               m_setup(M_MODEOK|M_DEBUG);
  191.               m_push(P_EVENT|P_MENU);
  192.               /*{{{  activate mouse buttons*/
  193.               if (mouse_number>1)
  194.                {
  195. #                define MGR_M_SEND_STR MGR_MOUSE_CODE " %P ."
  196.  
  197.                  strcpy(x,MGR_M_SEND_STR);
  198.                  if (mouse_mapping[1]!=O_NOP)
  199.                   { x[sizeof(MGR_M_SEND_STR)-2]=(char)2;
  200.                     m_setevent(BUTTON_2U,x);
  201.                   }
  202.                  if (mouse_number>2)
  203.                   { if (mouse_mapping[2]!=O_NOP)
  204.                      { x[sizeof(MGR_M_SEND_STR)-2]=(char)3;
  205.                        m_setevent(BUTTON_1U,x);
  206.                      }
  207.                     if (mouse_number>6)
  208.                      { if (mouse_mapping[6]!=O_NOP)
  209.                         { x[sizeof(MGR_M_SEND_STR)-2]=(char)7;
  210.                           m_setevent(BUTTON_2,x);
  211.                         }
  212.                        if (mouse_number>7)
  213.                         { if (mouse_mapping[7]!=O_NOP)
  214.                            { x[sizeof(MGR_M_SEND_STR)-2]=(char)8;
  215.                              m_setevent(BUTTON_1,x);
  216.                            }
  217.                         }
  218.                      }
  219.                   }
  220.  
  221. #                undef MGR_M_SEND_STR
  222.                }
  223.               /*}}}  */
  224.               /*{{{  activate redraw/reshape*/
  225.               strcpy(x,MGR_MOUSE_CODE);
  226.               strcat(x,"-");
  227.               m_setevent(RESHAPE,x);
  228.               m_setevent(REDRAW,x);
  229.               /*}}}  */
  230.               m_flush();
  231.             }
  232.             /*}}}  */
  233. #     endif
  234.       }
  235. #  endif
  236.   /*}}}  */
  237.   /*{{{  get old mode and initialize structs for new mode*/
  238.   if (tcgetattr(fileno(kbd_file), &orig)<0 && kbd_is_terminal)
  239.   { unsigned char *t;
  240.  
  241.     t=get_msg(F_TCG_F,strerror(errno));
  242.     if (running)
  243.        exit_origami(r_init_err,t);
  244.     else
  245.      { oputs(t);
  246.        exit(r_init_err);
  247.      }
  248.   }
  249.   /*}}}  */
  250.   eight_bits=(orig.c_cflag&CS8)==CS8;
  251.   if (!eight_bits && dsp.high==norm_dsp)
  252.      dsp.high=dsp.base;
  253.   work=orig;
  254.   work.c_iflag=BRKINT;
  255.   work.c_lflag=ISIG;
  256.   /*{{{  if suspend is disabled, set no_pipe=True*/
  257. #  ifdef VSUSP
  258.      if (work.c_cc[VSUSP]==(cc_t)_POSIX_VDISABLE)
  259.         no_suspend=True;
  260. #  endif
  261.   /*}}}  */
  262.   /* disable all signal keys */
  263.   memset(work.c_cc,_POSIX_VDISABLE,NCCS);
  264.   work.c_cc[VTIME]=0;
  265.   work.c_cc[VMIN]=1;
  266.   disable_abort();
  267.   enable_echo(!echo_disabled);
  268. }
  269. /*}}}  */
  270. /*{{{  reset_keyboard*/
  271. public void reset_keyboard(void)
  272. {
  273.    tcsetattr(fileno(kbd_file), TCSANOW, &orig);
  274. #  ifdef XTERM
  275.      if (use_mouse==xterm) send_s_terminal((unsigned char*)XTERM_END_BP);
  276. #  endif
  277. #  ifdef MGR
  278.      if (use_mouse==mgr)
  279.       { fflush(stdout);
  280.         m_popall();
  281.         m_flush();
  282.       }
  283. #  endif
  284. }
  285. /*}}}  */
  286. /*{{{  chg_w_title*/
  287. #ifdef WINDOW_TITLE_CHANGE
  288.    public void chg_w_title(char const *s)
  289.    {
  290.      if (chg_title)
  291.       /*{{{  chg window title*/
  292.       { if (!s)
  293.          /*{{{  buildt title from Origami,version,diredt,wname and filename (bd.buff_width*3/4)*/
  294.          { title_op(WINTITLE);
  295.            s=(char*)statline;
  296.          }
  297.          /*}}}  */
  298.         ocl_msg("window-title-chg",0);
  299. #       ifdef XTERM
  300.            if (use_mouse==xterm)
  301.             { XTERM_CHGNAME((char*)s); }
  302. #       endif
  303.       }
  304.       /*}}}  */
  305.    }
  306. #endif
  307. /*}}}  */
  308.  
  309. /*{{{  read_err*/
  310. public void read_err(FILE * const f,char * const s)
  311. { size_t readcount;
  312.  
  313.   do
  314.    { errno=0;
  315.      readcount=read(fileno(f),s,(size_t)1);
  316.    }
  317.   while
  318.    (    errno==EINTR
  319. #    ifdef EAGAIN
  320.      || errno==EAGAIN
  321. #    endif
  322.    );
  323.   if (readcount!=1)
  324.      exit_origami(r_eof,(unsigned char *)STR_EOF);
  325. }
  326. /*}}}  */
  327. /*{{{  get_key*/
  328. public TOKEN get_key (void)
  329. {
  330.   oflush;
  331.   ocl_msg("keyboard %d",ocl_var[var_key_count].v);
  332.   for (;;)
  333.    {
  334.      /*{{{  variables*/
  335.      int result= keytabcont;
  336.      unsigned char ch=general_abort_key;
  337.      int lg=0;
  338.      /*}}}  */
  339.  
  340.      ocl_var[var_key_count].v+=1;
  341.      /*{{{  scan a keyboard-sequence 'til token is complete*/
  342.      while (result==keytabcont && !aborted) {
  343.        /*{{{  example for mouse-handling (active scan!)*/
  344. #       if 0
  345.           if (use_mouse==my-scanning-mouse-enum && mouse_pressed())
  346.            { check_time_event();
  347.              return_handle_click(x,y,button_code);
  348.            }
  349.           /*
  350.            * This is an example for using a mouse, not a implementation!
  351.            *   mouse_event()
  352.            *   should be something, scanning the mouse and returning
  353.            *   True< if mousebuttons are pressed
  354.            *         x,y and button_code should be defined during mouse_event.
  355.            *   x: clickposition in line (1=left,width=right)
  356.            *   y: clickline (1=top,height=bottom)
  357.            *   button_code: coding which button is pressed
  358.            *     if button and shift/button should have different meanings,
  359.            *     use different codes
  360.            */
  361. #       endif
  362.        /*}}}  */
  363.        /*{{{  read from keyboard*/
  364.        { if (scr_off)
  365.           { ocl_msg("read on scroff",0);
  366.             ori_abort(~SIGINT);
  367.             return(O_BREAK);
  368.           }
  369.          read_err(kbd_file,(char*)&ch);
  370.          ocl_key((int)ch);
  371.        }
  372.        /*}}}  */
  373.        lg++;
  374.        result=find_key(ch);
  375.        if (echo_active)
  376.         /*{{{  echo-handling*/
  377.         { enum dsp_size old_mode;
  378.  
  379.           old_mode=dsp.norm;
  380.           dsp.norm=norm_dsp;
  381.           if (result==keytabcont)
  382.            /*{{{  show sequence of pressed keys*/
  383.            {
  384.              /*{{{  maybe prepare message line in first loop*/
  385.              if (lg==1)
  386.               { moveclreol(message_line,1);
  387.                 move_cursor_to(message_line,1);
  388.               }
  389.              /*}}}  */
  390.              /*{{{  print the coding for ch*/
  391.              { static unsigned char meta[]="M-";
  392.                static unsigned char ctrl[]="C-x ";
  393.                unsigned char *cp;
  394.  
  395.                /*{{{  cp=coding of current char*/
  396.                if (ch=='\033')
  397.                   cp=meta;
  398.                else
  399.                 { cp=ctrl;
  400.                   if (ch==127)
  401.                      *(cp+2)='?';
  402.                   else if (hz && ch=='~')
  403.                      *(cp+2)=(unsigned char)HZ_TILDE;
  404.                   else if ((unsigned int)ch>=(unsigned int)' ')
  405.                      *(cp+=2)=ch;
  406.                   else
  407.                      *(cp+2)=ctrl_decode[ch];
  408.                 }
  409.                /*}}}  */
  410.                prt_bin_text(0,4,False,cp);
  411.                oflush;
  412.              }
  413.              /*}}}  */
  414.            }
  415.            /*}}}  */
  416.           else
  417.              moveclreol(message_line,1);
  418.           dsp.norm=old_mode;
  419.         }
  420.         /*}}}  */
  421.      }
  422.      /*}}}  */
  423.      if (aborted)
  424.       { ocl_msg("read break=%d",O_BREAK);
  425.         return(O_BREAK);
  426.       }
  427.      /*{{{  handle mice, sending to stdin*/
  428. #     ifdef XTERM
  429.         if (result==K_MOUSE && use_mouse==xterm)
  430.          /*{{{  get mouse-info from kbd, x-coding*/
  431.          { int x,y,b;
  432.  
  433.            read_err(kbd_file,(char*)&ch);b=ch-' ';
  434.            read_err(kbd_file,(char*)&ch);x=ch-' ';
  435.            read_err(kbd_file,(char*)&ch);y=ch-' ';
  436.            ocl_msg("click xterm",0);
  437.            check_time_event();
  438.            result=handle_click(x,y,b);
  439.  
  440.            ocl_msg("read mouse=%d",result);
  441.  
  442.            return(result);
  443.          }
  444.          /*}}}  */
  445. #     endif
  446. #     ifdef MGR
  447.         if (result==K_MOUSE && use_mouse==mgr)
  448.          /*{{{  get mouse-info from kbd, mgr-coding*/
  449.          { int x=0,y=0;
  450.            char s[10];
  451.            char *p;
  452.  
  453.            p=s;
  454.            read_err(kbd_file,p);
  455.            if (*p=='-')
  456.             { win_changed=True;continue; }
  457.            for (;;)
  458.             { read_err(kbd_file,p);
  459.               if (!isdigit(*p))
  460.                  break;
  461.               p++;
  462.             }
  463.            *p='\0';
  464.            x=atoi(s)+1;
  465.            p=s;
  466.            for (;;)
  467.             { read_err(kbd_file,p);
  468.               if (!isdigit(*p))
  469.                  break;
  470.               p++;
  471.             }
  472.            *p=0;
  473.            y=atoi(s)+1;
  474.            read_err(kbd_file,(char*)&ch);
  475.            ocl_msg("click mgr",0);
  476.            check_time_event();
  477.            result=handle_click(x,y,ch-1);
  478.  
  479.            ocl_msg("read mouse=%d",result);
  480.  
  481.            return(result);
  482.          }
  483.          /*}}}  */
  484. #     endif
  485.      /*}}}  */
  486.      check_time_event();
  487.      if (ch==general_abort_key && !quote_used)
  488.       /*{{{  break macros and return O_BREAK*/
  489.       { ocl_msg("got abort from stdin",0);
  490.         ori_abort(~SIGINT);
  491.  
  492.         ocl_msg("read ch=ab=%d",O_BREAK);
  493.  
  494.         return(O_BREAK);
  495.       }
  496.       /*}}}  */
  497.      if (result!=keytabknb)
  498.       /*{{{  return char or coded macro*/
  499.       { if (result!=keytabend)
  500.          { ocl_msg("read op=%d",result);
  501.            return(result);
  502.          }
  503.         else if (lg==1)
  504.          { ocl_msg("read ch=%d",ch);
  505.            return(ch);
  506.          }
  507.       }
  508.       /*}}}  */
  509.      if (knb_macro)
  510.         call_number_macro(knb_macro);
  511.      if (echo_active)
  512.         msg_message(M_NOT_BOUND);
  513.      ocl_msg("read NOP=%d",O_NOP);
  514.      return(O_PROMPT);
  515.    }
  516. }
  517. /*}}}  */
  518.